// This kernel perform vectorized floating-point addition/multiplication
// to demonstrate how parallel processing can accelerate computation
// 2020.06.17 by wangdong@bjtu.edu.cn
//#include "ap_int.h"
// #include <stdio.h> 


#include "custypedef.h"

extern "C" {
void featureRead(
            	AIN_type *A_in,
				uint data_num,
				REFERENCE_STREAM(k2k<vec_type>, 32, img_channels)
				)
{
	#pragma HLS INTERFACE m_axi port = A_in  offset = slave bundle = gmem0 //num_read_outstanding=1 max_read_burst_length=1
	#pragma HLS INTERFACE axis  port = img_channels depth=32

	AIN_type img_ori_0[BUFFER_DEPTH * 2/AIN_TYPE];
	AIN_type img_ori_1[BUFFER_DEPTH * 2/AIN_TYPE];
	AIN_type img_ori_2[BUFFER_DEPTH * 2/AIN_TYPE];
	bool flag = 0;
	
	volatile int Rdcnt = 0;
	for(uint k = 0; k<DATA_SIZE_M/PE_NUM_M; k++){
		
		for(int i = -(VEC_SIZE) + 1; i < DATA_SIZE_H - DATA_SIZE_K + 1; i++)
		{
			for(int nn = 0; nn < DATA_SIZE_N; nn++){
				#pragma HLS PIPELINE II=1 rewind
				for(uint j = 0; j< DATA_SIZE_W / AIN_TYPE; j++){
					img_ori_2[j + nn * DATA_SIZE_W/AIN_TYPE + flag * BUFFER_DEPTH/AIN_TYPE] = A_in[j + (i + 2) * DATA_SIZE_W/AIN_TYPE + nn * DATA_SIZE_W * DATA_SIZE_H/AIN_TYPE];
				}
			}
			for(uint s = 0; s<DATA_SIZE_W - DATA_SIZE_K + 1; s++){
				for(int nn = 0; nn < DATA_SIZE_N; nn++){
					#pragma HLS PIPELINE II=1 rewind
					for(uint s2 = 0; s2 < DATA_SIZE_K; s2++){
						k2k<vec_type> _trans_img_oris;
						DATA_TYPE tmp[9];
						tmp[0+s2*DATA_SIZE_K] = img_ori_0[(s + s2)/AIN_TYPE + nn * DATA_SIZE_W/AIN_TYPE + flag * BUFFER_DEPTH/AIN_TYPE].data[(s + s2)%AIN_TYPE];
						tmp[1+s2*DATA_SIZE_K] = img_ori_1[(s + s2)/AIN_TYPE + nn * DATA_SIZE_W/AIN_TYPE + flag * BUFFER_DEPTH/AIN_TYPE].data[(s + s2)%AIN_TYPE];
						tmp[2+s2*DATA_SIZE_K] = img_ori_2[(s + s2)/AIN_TYPE + nn * DATA_SIZE_W/AIN_TYPE + flag * BUFFER_DEPTH/AIN_TYPE].data[(s + s2)%AIN_TYPE];

						img_ori_0[(s + s2)/AIN_TYPE + nn * DATA_SIZE_W/AIN_TYPE + (!flag) * BUFFER_DEPTH/AIN_TYPE].data[(s + s2)%AIN_TYPE] = tmp[1+s2*DATA_SIZE_K];
						img_ori_1[(s + s2)/AIN_TYPE + nn * DATA_SIZE_W/AIN_TYPE + (!flag) * BUFFER_DEPTH/AIN_TYPE].data[(s + s2)%AIN_TYPE] = tmp[2+s2*DATA_SIZE_K];
						++Rdcnt;
						if(i>=0){
							for(uint mm = 0; mm < DATA_SIZE_K; mm++){
								_trans_img_oris.data(GET_BIT(DATA_TYPE)*(mm+1)-1, GET_BIT(DATA_TYPE)*mm) = tmp[mm+s2*DATA_SIZE_K];
							}
							img_channels.write(_trans_img_oris);
						}
					}
				}
			}
			flag = !flag;
		}
	}
}
}
